package deployr.core;

import java.util.*;

public class WebAppDiff {

	private Map<String, String> added = new HashMap<String, String>();

	private Map<String, String> updated = new HashMap<String, String>();

	private Map<String, String> removed = new HashMap<String, String>();

	private String root;

	public WebAppDiff() {}

	public WebAppDiff(String diff) {}

	public WebAppDiff(WebApp webapp1, WebApp webapp2) {
		List<String> list1 = list(webapp1);
		List<String> list2 = list(webapp2);

		addedOrRemoved(list1, list2);
		rememberRootOf(webapp1, webapp2);
		updated();
	}

	private void addedOrRemoved(List<String> list1, List<String> list2) {
		List<Difference> differences = diff(list1, list2);
		for (Difference aDifference : differences) {
			appendRemovedFrom(list1, aDifference);
			appendAddedFrom(list2, aDifference);
		}
	}

	private void appendAddedFrom(final List<String> set2, Difference difference) {
		for (int i = difference.getAddedStart(); i <= difference.getAddedEnd(); i++) {
			put(added, set2.get(i));
		}
	}

	private void appendRemovedFrom(final List<String> set1, Difference difference) {
		for (int i = difference.getDeletedStart(); i <= difference.getDeletedEnd(); i++) {
			put(removed, set1.get(i));
		}
	}

	public String content() {
		return null;
	}

	private List<Difference> diff(List<String> set1, List<String> set2) {
		return new Diff(set1, set2).diff();
	}

	private List<String> list(WebApp webapp) {
		List<String> set = new LinkedList<String>();
		Scanner scanner = new Scanner(webapp.checksum()).useDelimiter("\n");
		while (scanner.hasNext()) {
			set.add(scanner.next());
		}
		return set;
	}

	private void put(Map<String, String> index, String string) {
		String md5 = string.replaceAll(" .*$", "");
		String path = string.replaceAll("^.* ", "");
		index.put(path, md5);
	}

	private void rememberRootOf(WebApp webapp1, WebApp webapp2) {
		String root1 = webapp1.root();
		String root2 = webapp2.root();

		this.root = root2;
	}

	public String summary() {
		return null;
	}

	private void updated() {
		List<String> toBeUpdated = new LinkedList<String>();
		for (String possibleUpdated : added.keySet()) {
			if (removed.containsKey(possibleUpdated)) {
				toBeUpdated.add(possibleUpdated);
			}
		}

		for (String path : toBeUpdated) {
			updated.put(path, added.get(path));
			added.remove(path);
			removed.remove(path);
		}
	}

	public WebApp webapp() {
		return new WebApp(root, added, updated, removed.keySet());
	}

}
